﻿using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using RikaScript.Exception;
using RikaScript.Libs.Base;

namespace RikaScript.Libs
{
    /*
     * 更新日志
     * v0.1: 创建类库，实现List和Dict的增删改查，和 mkstr、json 功能
     */
    /// <summary>
    /// 数据结构类库
    /// </summary>
    [Library(Name = "ds", Help = "RikaScript 标准数据结构类库，支持List和Dict两种类型", Version = "0.1.0")]
    public class DataStructLib : ScriptLibBase
    {
        [Method(Help = "从数据结构中获取一个数据，如果结构是List，key应该为整数，如果结构是Dict，key应该是唯一标识")]
        public object get(object ds, object key)
        {
            switch (ds)
            {
                case IList list:
                    return list[(int) key.Long()];
                case IDictionary dict:
                    return dict[key];
                default:
                    throw new NotSupportDataStructException(ds.GetType().FullName);
            }
        }

        [Method(Help = "给数据结构的某个位置设置数据，如果结构是List则pos应该为整数，如果结构是Dict，key应该是唯一标识")]
        public void set(object ds, object key, object value)
        {
            switch (ds)
            {
                case IList list:
                    list[(int) key.Long()] = value;
                    break;
                case IDictionary dict:
                    dict[key] = value;
                    break;
                default:
                    throw new NotSupportDataStructException(ds.GetType().FullName);
            }
        }

        [Method(Help = "从数据结构中删除某个元素，返回结构自身，list直接删除元素，dict删除key")]
        public object remove(object ds, object obj)
        {
            switch (ds)
            {
                case IList list:
                    list.Remove(obj);
                    break;
                case IDictionary dict:
                    dict.Remove(obj);
                    break;
                default:
                    throw new NotSupportDataStructException(ds.GetType().FullName);
            }

            return ds;
        }

        [Method(Help = "创建并返回一个数据结构，类型可选 list 或 dict")]
        public object create(object type)
        {
            switch (type.String())
            {
                case "list":
                    return new List<object>();
                case "dict":
                    return new Dictionary<object, object>();
                default:
                    throw new NotSupportDataStructException(type.String());
            }
        }

        [Method(Help = "返回数据结构的长度")]
        public object len(object ds)
        {
            switch (ds)
            {
                case ICollection coll:
                    return coll.Count;
                default:
                    throw new NotSupportDataStructException(ds.GetType().FullName);
            }
        }

        [Method(Help = "获取全部的key，List返回由下标构成的List，Dict返回全部key构成的List")]
        public object keys(object ds)
        {
            switch (ds)
            {
                case IList list:
                    var res = new List<int>();
                    for (var i = 0; i < list.Count; i++)
                        res.Add(i);

                    return res;
                case IDictionary dict:
                    return dict.Keys.Cast<object>().ToList();
                default:
                    throw new NotSupportDataStructException(ds.GetType().FullName);
            }
        }

        [Method(Help = "获取全部的value，List返回本身，Dict返回由全部数值构成的List")]
        public object values(object ds)
        {
            switch (ds)
            {
                case IList list:
                    return ds;
                case IDictionary dict:
                    return dict.Values.Cast<object>().ToList();
                default:
                    throw new NotSupportDataStructException(ds.GetType().FullName);
            }
        }

        [Method(Name = "in", Help = "判断某个值是否在数据结构中")]
        public object isin(object ds, object value)
        {
            switch (ds)
            {
                case IList list:
                    return list.Contains(value);
                case IDictionary dict:
                    return dict.Contains(value);
                default:
                    throw new NotSupportDataStructException(ds.GetType().FullName);
            }
        }

        [Method(Help = "由str参数分隔多个元素，返回格式化后的数据结构字符串")]
        public object mkstr(object ds, object str)
        {
            var sb = new StringBuilder();

            var seq = str.String();
            switch (ds)
            {
                case IList list:
                    sb.Append("[");
                    var listCount = list.Count;
                    for (var i = 0; i < listCount; i++)
                    {
                        sb.Append(list[i] is string s ? "\"{0}\"".Format(s) : list[i]);
                        if (i < list.Count - 1) sb.Append(seq);
                    }

                    sb.Append("]");

                    break;
                case IDictionary dict:
                    sb.Append("{");
                    var keys = dict.Keys.Cast<object>().ToList();
                    var dictCount = keys.Count;
                    for (var i = 0; i < dictCount; i++)
                    {
                        sb.Append(keys[i] is string keysS ? "\"{0}\"".Format(keysS) : keys[i]);
                        sb.Append(": ");
                        sb.Append(dict[keys[i]] is string dictS ? "\"{0}\"".Format(dictS) : dict[keys[i]]);
                        if (i < dictCount - 1) sb.Append(seq);
                    }

                    sb.Append("}");
                    break;
                default:
                    throw new NotSupportDataStructException(ds.GetType().FullName);
            }


            return sb.ToString();
        }

        [Method(Help = "格式化到尽量标准的JSON格式")]
        public object json(object ds)
        {
            return mkstr(ds, ", ");
        }

        [Method(Help = "在List的指定位置插入数据")]
        public void insert(object ds, object index, object value)
        {
            if (!(ds is IList list)) throw new NotSupportDataStructException(ds.GetType().FullName);
            list.Insert((int) index.Long(), value);
        }

        [Method(Help = "从List中按照index删除元素，返回结构自身")]
        public object removeAt(object ds, object index)
        {
            if (!(ds is IList list)) throw new NotSupportDataStructException(ds.GetType().FullName);
            list.RemoveAt((int) index.Long());
            return ds;
        }

        [Method(Help = "针对List的操作，push进一个数据，返回List本身，方便List调用")]
        public object push(object ds, object value)
        {
            if (!(ds is IList list)) throw new NotSupportDataStructException(ds.GetType().FullName);
            list.Add(value);
            return ds;
        }

        [Method(Help = "针对List的操作，pop一个数据")]
        public object pop(object ds)
        {
            if (!(ds is IList list)) throw new NotSupportDataStructException(ds.GetType().FullName);
            var res = list[list.Count - 1];
            list.RemoveAt(list.Count - 1);
            return res;
        }

        [Method(Help = "针对List的操作，peek一个数据")]
        public object peek(object ds)
        {
            if (!(ds is IList list)) throw new NotSupportDataStructException(ds.GetType().FullName);
            return list[list.Count - 1];
        }
    }

    public class DataStructException : RikaScriptException
    {
        public DataStructException(string info) : base(info)
        {
        }
    }

    public class NotSupportDataStructException : DataStructException
    {
        /// <summary>
        /// 不支持的数据类型
        /// </summary>
        /// <param name="info">数据类型名字</param>
        public NotSupportDataStructException(string info) : base("不支持的数据类型: " + info)
        {
        }
    }
}